#include <iostream>
#include <sys/wait.h>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#include <string.h>
#include <cerrno>
#include <signal.h>
using namespace std;
#include "ThreadPool.hpp"
#include "Task.hpp"


class TcpSever
{
  private:
    int _sockfd;
    int _port;
    ThreadPool<Task>* _tp;
  public:
    void Init()
    {
      _sockfd = socket(AF_INET, SOCK_STREAM , 0);
      if (_sockfd < 0)
      {
        cout << "socket error" << endl;
        exit(2);
      }

      struct sockaddr_in local;
      memset(&local , 0 , sizeof(local));
      local.sin_family = AF_INET;
      local.sin_port = htons(_port);
      local.sin_addr.s_addr = INADDR_ANY;
      if(bind(_sockfd , (struct sockaddr*)&local , sizeof(sockaddr)) < 0)
      {
        cout << "bind error" << endl;
        exit(3);
      }

      if(listen(_sockfd , 5) < 0)
      {
        cout << "listen error" << endl;
        exit(4);
      }
     
      _tp = new ThreadPool<Task>;
    }

  static void Service(int sock)
  {

    cout << "get a new linl :  " << sock  << endl;
    char buff[1024];
    while(true)
    {
      ssize_t size = read(sock , buff , sizeof(buff) - 1);
      if (size > 0)
      {
        buff[size] = 0; // '\0'
        cout << buff << endl;
        write(sock , buff , size);
      }
      else if (size == 0)
      {
        cout << "read close" << endl; 
        break;
      }
      else 
      {
        cout << "unknown error" << endl;
      }
   }
    close(sock);
    cout << "Service end sock closed" << endl;
  }

  static void* Rontine(void* arg)
  {
    pthread_detach(pthread_self());
    int* p = (int*)arg;

    int sock = *p;
    Service(sock);
    return nullptr;
  }

  void Start()
  {
    _tp->ThreadPoolInit();
    while(true)
    {
      // accept 
      struct sockaddr_in peer; 
      memset(&peer , '\0' , sizeof(peer));
      socklen_t len = sizeof(peer);

      int sock = accept(_sockfd , (struct sockaddr*)&peer , &len);
      if (sock < 0)
      {
        cout << "accept error" << endl; 
        continue;
      }

      Task task(sock);
      _tp->Push(task);
    }
  }
  public:
    TcpSever(int port)
      :_sockfd(-1),
      _port(port),
       _tp(nullptr)
    {}
    ~TcpSever()
    {
      if (_sockfd > 0)
      {
         close(_sockfd);
      }

      delete _tp;
    }
};


int main(int argc , char* argv[])
{
  if (argc != 2)
  {
    cout << "argc error" << endl;
    exit(2);
  }

  int port = atoi(argv[1]);

  auto* svr = new TcpSever(port);
  svr->Init();
  svr->Start();
  return 0;
}
